package com.jzo2o.market.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.expcetions.BadRequestException;
import com.jzo2o.common.utils.*;
import com.jzo2o.market.constants.TabTypeConstants;
import com.jzo2o.market.enums.ActivityStatusEnum;
import com.jzo2o.market.mapper.ActivityMapper;
import com.jzo2o.market.mapper.CouponMapper;
import com.jzo2o.market.model.domain.Activity;
import com.jzo2o.market.model.domain.Coupon;
import com.jzo2o.market.model.domain.CouponWriteOff;
import com.jzo2o.market.model.dto.request.ActivityQueryForPageReqDTO;
import com.jzo2o.market.model.dto.request.ActivitySaveReqDTO;
import com.jzo2o.market.model.dto.response.ActivityInfoResDTO;
import com.jzo2o.market.service.IActivityService;
import com.jzo2o.market.service.ICouponService;
import com.jzo2o.market.service.ICouponWriteOffService;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

import static com.jzo2o.market.enums.ActivityStatusEnum.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author itcast
 * @since 2023-09-16
 */
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements IActivityService {
    private static final int MILLION = 1000000;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private ICouponService couponService;

    @Resource
    private ICouponWriteOffService couponWriteOffService;

    @Resource
    private ActivityMapper activityMapper;

    @Resource
    private CouponMapper couponMapper;


    /**
     * 保存优惠券
     *
     * @param activitySaveReqDTO
     */
    @Override
    public void saveActivity(ActivitySaveReqDTO activitySaveReqDTO) {
        activitySaveReqDTO.check();

        if (activitySaveReqDTO.getDistributeStartTime().isAfter(LocalDateTime.now())) {
            activitySaveReqDTO.setStatus(NO_DISTRIBUTE.getStatus());
        } else if (activitySaveReqDTO.getDistributeStartTime().isBefore(LocalDateTime.now()) || activitySaveReqDTO.getDistributeEndTime().isAfter(LocalDateTime.now()) || activitySaveReqDTO.getDistributeEndTime().isEqual(LocalDateTime.now())) {
            activitySaveReqDTO.setStatus(DISTRIBUTING.getStatus());
        } else if (activitySaveReqDTO.getDistributeEndTime().isBefore(LocalDateTime.now())) {
            activitySaveReqDTO.setStatus(LOSE_EFFICACY.getStatus());
        }
        //属性拷贝
        Activity activity = BeanUtils.copyBean(activitySaveReqDTO, Activity.class);
        //判断是新增还是修改
        if (activitySaveReqDTO.getId() != null) {
            baseMapper.updateById(activity);
        } else {
            baseMapper.insert(activity);
        }

    }

    /**
     * 分页查询优惠券
     *
     * @param activityQueryForPageReqDTO
     * @return
     */
    @Override
    public IPage<ActivityInfoResDTO> queryActivityForPage(ActivityQueryForPageReqDTO activityQueryForPageReqDTO) {
        // 创建分页对象
        Page<ActivityInfoResDTO> page = new Page<>(activityQueryForPageReqDTO.getPageNo().intValue(), activityQueryForPageReqDTO.getPageSize().intValue());

        // 执行分页查询
        Long id = activityQueryForPageReqDTO.getId();
        String name = activityQueryForPageReqDTO.getName();
        Integer type = activityQueryForPageReqDTO.getType();
        Integer status = activityQueryForPageReqDTO.getStatus();
        IPage<ActivityInfoResDTO> result = activityMapper.selectActivity(page, id, name, type, status);

        // 遍历查询结果，设置每个活动的领取数量和核销数量
        for (ActivityInfoResDTO activity : result.getRecords()) {
            // 计算领取数量
            activity.setReceiveNum(activity.getTotalNum() - activity.getStockNum());
            // 计算核销数量
            int writeOffNum = couponMapper.writeOffNum(activity.getId());
            activity.setWriteOffNum(writeOffNum);
        }
        return result;
    }

    /**
     * 根据id查询优惠券详情
     *
     * @param id
     * @return
     */
    @Override
    public ActivityInfoResDTO getActivityById(Long id) {
        Activity activity = baseMapper.selectById(id);
        ActivityInfoResDTO activityInfoResDTO = new ActivityInfoResDTO();
        BeanUtil.copyProperties(activity, activityInfoResDTO);
        // 计算领取数量
        activityInfoResDTO.setReceiveNum(activity.getTotalNum() - activity.getStockNum());
        // 计算核销数量
        int writeOffNum = couponMapper.writeOffNum(activity.getId());
        activityInfoResDTO.setWriteOffNum(writeOffNum);
        return activityInfoResDTO;
    }

    /**
     * 撤销优惠券
     *
     * @param id
     */
    @Override
    public void revokeActivity(Long id) {
        Activity activity = baseMapper.selectById(id);
        if (activity.getStatus() == NO_DISTRIBUTE.getStatus() || activity.getStatus() == DISTRIBUTING.getStatus()) {
            activity.setStatus(VOIDED.getStatus());
            baseMapper.updateById(activity);
            //将所有抢到本活动优惠券的状态为未使用的记录的状态更改为“已失效”，coupon
            couponMapper.updateStatus(id);
        }
    }

    /**
     * 使用定时任务自动变更活动状态
     */
    @XxlJob("activityStatusJob")
    public void changeActivityStatus() {
        LocalDateTime now = LocalDateTime.now();
        List<Activity> activityList = baseMapper.selectList(new QueryWrapper<Activity>().lambda()
                .eq(Activity::getStatus, NO_DISTRIBUTE.getStatus())
                .ge(Activity::getDistributeEndTime, now)
                .le(Activity::getDistributeStartTime, now));
        for (Activity activity : activityList) {
            activity.setStatus(DISTRIBUTING.getStatus());
            baseMapper.updateById(activity);
        }

        List<Activity> activityList1 = baseMapper.selectList(new QueryWrapper<Activity>().lambda()
                .eq(Activity::getStatus, DISTRIBUTING.getStatus())
                .le(Activity::getDistributeEndTime, now));
        for (Activity activity : activityList1) {
            activity.setStatus(LOSE_EFFICACY.getStatus());
            baseMapper.updateById(activity);
        }


    }
}
